package cn.iocoder.yudao.module.reclaim.service.productcheckres;

import cn.hutool.core.util.ObjectUtil;
import cn.iocoder.yudao.framework.common.enums.metal.MetalTypeEnum;
import cn.iocoder.yudao.framework.common.enums.trade.TransactionTypeEnum;
import cn.iocoder.yudao.framework.common.pojo.PageResult;
import cn.iocoder.yudao.framework.common.util.object.BeanUtils;
import cn.iocoder.yudao.module.pay.api.wallet.PayWalletApi;
import cn.iocoder.yudao.module.reclaim.api.checkres.dto.ReclaimCheckResDTO;
import cn.iocoder.yudao.module.reclaim.controller.admin.productcheckres.vo.ReclaimCheckResPageReqVO;
import cn.iocoder.yudao.module.reclaim.controller.admin.productcheckres.vo.ReclaimCheckResRespVO;
import cn.iocoder.yudao.module.reclaim.controller.admin.productcheckres.vo.ReclaimCheckResSaveReqVO;
import cn.iocoder.yudao.module.reclaim.convert.CheckResConvert;
import cn.iocoder.yudao.module.reclaim.dal.dataobject.productcheckres.ReclaimCheckDeductItemDO;
import cn.iocoder.yudao.module.reclaim.dal.dataobject.productcheckres.ReclaimCheckResDO;
import cn.iocoder.yudao.module.reclaim.dal.mysql.productcheckres.ReclaimCheckDeductItemMapper;
import cn.iocoder.yudao.module.reclaim.dal.mysql.productcheckres.ReclaimCheckResMapper;
import cn.iocoder.yudao.module.trade.api.order.TradeOrderApi;
import cn.iocoder.yudao.module.trade.api.order.dto.TradeOrderUpdateCheckDTO;
import jakarta.annotation.Resource;
import org.springframework.context.annotation.Lazy;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;
import org.springframework.validation.annotation.Validated;

import java.math.BigDecimal;
import java.math.RoundingMode;
import java.util.ArrayList;
import java.util.List;

import static cn.iocoder.yudao.framework.common.exception.util.ServiceExceptionUtil.exception;
import static cn.iocoder.yudao.module.reclaim.enums.ErrorCodeConstants.PRODUCT_CHECK_RES_NOT_EXISTS;

/**
 * 回收核验结果 Service 实现类
 *
 * @author FFFF
 */
@Service
@Validated
public class ReclaimCheckResServiceImpl implements ReclaimCheckResService {

    @Resource
    private ReclaimCheckResMapper productCheckResMapper;
    @Resource
    private ReclaimCheckDeductItemMapper productCheckDeductItemMapper;
    @Resource
    @Lazy
    private TradeOrderApi tradeOrderApi;
    @Resource
    private PayWalletApi payWalletApi;
    @Override
    @Transactional(rollbackFor = Exception.class)
    public Long createProductCheckRes(ReclaimCheckResSaveReqVO createReqVO) {
        // 插入
        ReclaimCheckResDO checkRes = BeanUtils.toBean(createReqVO, ReclaimCheckResDO.class);
        productCheckResMapper.insert(checkRes);

        // 插入子表
        createProductCheckDeductItemList(checkRes.getId(), createReqVO.getCheckDeductItems());
        if (TransactionTypeEnum.STORE_METAL.getType().equals(createReqVO.getOrderType())) {
//            // 进行钱包入库
//            payWalletApi.addWalletBalanceByStorage(updateReqVO.getOrderNo(), updateReqVO.getMaterialType(), updateReqVO.getWeightCheckAfter());
//            tradeOrderApi.updateOrderStatus(updateReqVO.getOrderNo());
        } else {
            TradeOrderUpdateCheckDTO updateCheckDTO = buildUpdateCheck(createReqVO);
            tradeOrderApi.adjustPriceByCheck(updateCheckDTO);
        }
        // 返回
        return checkRes.getId();
    }

    @Override
    @Transactional(rollbackFor = Exception.class)
    public void updateProductCheckRes(ReclaimCheckResSaveReqVO updateReqVO) {
        // 校验存在
        validateProductCheckResExists(updateReqVO.getId());
        // 更新
        ReclaimCheckResDO updateObj = BeanUtils.toBean(updateReqVO, ReclaimCheckResDO.class);
        productCheckResMapper.updateById(updateObj);
        // 更新子表
        updateProductCheckDeductItemList(updateReqVO.getId(), updateReqVO.getCheckDeductItems());
        if (TransactionTypeEnum.STORE_METAL.getType().equals(updateReqVO.getOrderType())) {
//            // 进行钱包入库
//            payWalletApi.addWalletBalanceByStorage(updateReqVO.getOrderNo(), updateReqVO.getMaterialType(), updateReqVO.getWeightCheckAfter());
//            tradeOrderApi.updateOrderStatus(updateReqVO.getOrderNo());
        } else {
            // 更新订单价格
            TradeOrderUpdateCheckDTO updatePrice = buildUpdateCheck(updateReqVO);
            tradeOrderApi.adjustPriceByCheck(updatePrice);
        }
    }

    private TradeOrderUpdateCheckDTO buildUpdateCheck(ReclaimCheckResSaveReqVO updateReqVO) {
        TradeOrderUpdateCheckDTO res = new TradeOrderUpdateCheckDTO();
        res.setOrderNo(updateReqVO.getOrderNo())
                .setIsCheck(true)
                .setMetalType(updateReqVO.getMetalType())
                .setDeductTotal(BigDecimal.ZERO)
                .setDeductString("deduct_total:0")
                .setPurity(updateReqVO.getPurePercent())
                .setConvertWeight(updateReqVO.getWeightCheckAfter()
                        .multiply(updateReqVO.getPurePercent())
                        .divide(BigDecimal.valueOf(100), RoundingMode.HALF_UP)
                        .setScale(3, RoundingMode.HALF_UP));
        // 非贵金属
        if (MetalTypeEnum.valueOf(updateReqVO.getMetalType()) == null) {
            res.setConvertWeight(BigDecimal.ZERO);
            res.setDeductString("非贵金属,核验重量为0g");
            return res;
        }
        if (updateReqVO.getCheckDeductItems() != null) {
            StringBuilder deductDes = new StringBuilder();
            updateReqVO.getCheckDeductItems().forEach(item -> {
                res.setDeductTotal(res.getDeductTotal().add(item.getTotalPrice()));
                deductDes.append("deduct_name:").append(item.getItemName()).append(";")
                        .append("price:").append(item.getPrice()).append(";")
                        .append("num:").append(item.getItemNumber()).append(";")
                ;
            });
            deductDes.append("deduct_total:").append(res.getDeductTotal()).append("。");
            res.setDeductString(deductDes.toString());
        }
        return res;
    }

    @Override
    @Transactional(rollbackFor = Exception.class)
    public void deleteProductCheckRes(Long id) {
        // 校验存在
        validateProductCheckResExists(id);
        // 删除
        productCheckResMapper.deleteById(id);

        // 删除子表
        deleteProductCheckDeductItemByResId(id);
    }

    private void validateProductCheckResExists(Long id) {
        if (productCheckResMapper.selectById(id) == null) {
            throw exception(PRODUCT_CHECK_RES_NOT_EXISTS);
        }
    }

    @Override
    public ReclaimCheckResDO getProductCheckRes(Long id) {
        return productCheckResMapper.selectById(id);
    }

    @Override
    public PageResult<ReclaimCheckResDO> getProductCheckResPage(ReclaimCheckResPageReqVO pageReqVO) {
        return productCheckResMapper.selectPage(pageReqVO);
    }


    @Override
    public void createProductCheckRes(List<ReclaimCheckResDTO> itemList) {
        List<ReclaimCheckResDO> checkResDOS = new ArrayList<>(itemList.size());
        itemList.forEach(item -> checkResDOS.add(new ReclaimCheckResDO().setOrderNo(item.getOrderNo())));
        // 插入
        productCheckResMapper.insertBatch(checkResDOS);
    }

    @Override
    public ReclaimCheckResRespVO getProductCheckResByOrderNo(String orderNo) {
        ReclaimCheckResDO resDO =  productCheckResMapper.selectOne(ReclaimCheckResDO::getOrderNo, orderNo);
        if (ObjectUtil.isNotNull(resDO)) {
            List<ReclaimCheckDeductItemDO> itemDOList = getProductCheckDeductItemListByResId(resDO.getId());
            return CheckResConvert.INSTANCE.convert(resDO,itemDOList);
        } else {
            return null;
        }
    }

    // ==================== 子表（回收核验扣除项） ====================

    @Override
    public List<ReclaimCheckDeductItemDO> getProductCheckDeductItemListByResId(Long resId) {
        return productCheckDeductItemMapper.selectListByResId(resId);
    }

    private void createProductCheckDeductItemList(Long resId, List<ReclaimCheckDeductItemDO> list) {
        if (list == null || list.isEmpty()) {
            return;
        }
        list.forEach(o -> o.setResId(resId));
        productCheckDeductItemMapper.insertBatch(list);
    }

    private void updateProductCheckDeductItemList(Long resId, List<ReclaimCheckDeductItemDO> list) {
        deleteProductCheckDeductItemByResId(resId);
        if (list == null || list.isEmpty()) {
            return;
        }
        list.forEach(o -> o.setId(null).setUpdater(null).setUpdateTime(null)); // 解决更新情况下：1）id 冲突；2）updateTime 不更新
        createProductCheckDeductItemList(resId, list);
    }

    private void deleteProductCheckDeductItemByResId(Long resId) {
        productCheckDeductItemMapper.deleteByResId(resId);
    }

}